﻿// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
// (“Fluent UI”)。该示例仅供参考，
// 用以补充《Microsoft 基础类参考》和
// MFC C++ 库软件随附的相关电子文档。
// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
// 若要了解有关 Fluent UI 许可计划的详细信息，请访问
// https://go.microsoft.com/fwlink/?LinkId=238214.
//
// 版权所有(C) Microsoft Corporation
// 保留所有权利。

// DBBrowser.cpp: 定义应用程序的类行为。
//

#include "pch.h"
#include "framework.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "DBBrowser.h"

#include "CAttachDlg.h"
#include "CPreImportDlg.h"
#include "dbother.h"
#include <cwinhttp.h>
#include "CSegDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CDBBrowserApp

BEGIN_MESSAGE_MAP(CDBBrowserApp, CWinAppEx)
	ON_COMMAND(ID_APP_ABOUT, &CDBBrowserApp::OnAppAbout)
	ON_COMMAND(ID_FILE_OPEN, &CDBBrowserApp::OnFileOpen)
	ON_COMMAND(ID_FILE_ATTACH, &CDBBrowserApp::OnFileAttach)
	ON_COMMAND(ID_IMPORTTODB, &CDBBrowserApp::ImportCSVToDB)
	ON_COMMAND(ID_FILE_SAVE_TO, &CDBBrowserApp::OnFileSaveToTxt)
	ON_COMMAND(ID_FILE_SAVE_ALL, &CDBBrowserApp::ExportAllTableToFile)
	ON_COMMAND(ID_FILE_SAVE_INC, &CDBBrowserApp::OnFileSaveIncToTxt)
	ON_COMMAND(ID_FILE_CLOSEDB, &CDBBrowserApp::CloseDB)
	ON_UPDATE_COMMAND_UI_RANGE(ID_IMPORTTODB, ID_BEGIN, &CDBBrowserApp::OnUpdateStatic1)
	ON_UPDATE_COMMAND_UI(ID_EDIT_INSERT, &CDBBrowserApp::OnUpdateStatic1)
	ON_UPDATE_COMMAND_UI(ID_EDIT_INSCLIP, &CDBBrowserApp::OnUpdateStatic1)
	ON_UPDATE_COMMAND_UI(ID_EDIT_SQLRUN, &CDBBrowserApp::OnUpdateStatic1)
	ON_COMMAND(ID_BEGIN, &CDBBrowserApp::OnBegin)
	ON_COMMAND(ID_ENDEDIT, &CDBBrowserApp::OnEndedit)
	ON_COMMAND(ID_ROLLBACK, &CDBBrowserApp::OnRollback)
	ON_COMMAND(ID_AUTOTRANS, &CDBBrowserApp::OnAutoTrans)
	ON_UPDATE_COMMAND_UI(ID_AUTOTRANS, &CDBBrowserApp::OnUpdateAutoTrans)
	ON_UPDATE_COMMAND_UI(ID_TB_CLEAR, &CDBBrowserApp::OnUpdateTbClear)
	ON_UPDATE_COMMAND_UI(ID_TB_RENAME, &CDBBrowserApp::OnUpdateTbClear)
	ON_UPDATE_COMMAND_UI_RANGE(ID_ENDEDIT, ID_ROLLBACK, &CDBBrowserApp::OnUpdateTrans)
	ON_UPDATE_COMMAND_UI_RANGE(ID_SEARCHCOMBO, ID_SEARCHEDIT, &CDBBrowserApp::OnUpadteSearch)
	ON_COMMAND(ID_SEARCHEDIT, &CDBBrowserApp::OnSearchedit)
	ON_COMMAND(ID_SEARCHCOMBO, &CDBBrowserApp::OnSearchedit)
	ON_COMMAND(ID_COLCOMBO, &CDBBrowserApp::OnSearchedit)
	ON_COMMAND(ID_EDIT_DEL, &CDBBrowserApp::OnEditDel)
	ON_COMMAND(ID_EDIT_REFRESH, &CDBBrowserApp::ReFresh)
	ON_UPDATE_COMMAND_UI(ID_EDIT_DEL, &CDBBrowserApp::OnUpdateEditDel)
	ON_UPDATE_COMMAND_UI(ID_LIST_COPY, &CDBBrowserApp::OnUpdateEditDel)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CELL, &CDBBrowserApp::OnUpdateEditCell)
	ON_COMMAND(ID_EDIT_SQLRUN, &CDBBrowserApp::OnEditSqlrun)
	ON_COMMAND(ID_EDIT_INSERT, &CDBBrowserApp::OnEditInsert)
	ON_COMMAND(ID_EDIT_INSCLIP, &CDBBrowserApp::OnEditInsClip)
	ON_COMMAND(ID_BUTTON_RICHOK, &CDBBrowserApp::OnRichEditOK)
	ON_COMMAND(ID_TB_RENAME, &CDBBrowserApp::OnTbRename)
	ON_COMMAND(ID_CheckUpdate, &CDBBrowserApp::CheckUpdate)
	ON_COMMAND(ID_SEG_TEST, &CDBBrowserApp::SegTest)
	ON_COMMAND(ID_LIST_COPY, &CDBBrowserApp::OnEditCopy)
END_MESSAGE_MAP()


// CDBBrowserApp 构造

CDBBrowserApp::CDBBrowserApp() noexcept
{
	m_bHiColorIcons = TRUE;

	// 支持重新启动管理器
	//m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
#ifdef _MANAGED
	// 如果应用程序是利用公共语言运行时支持(/clr)构建的，则: 
	//     1) 必须有此附加设置，“重新启动管理器”支持才能正常工作。
	//     2) 在您的项目中，您必须按照生成顺序向 System.Windows.Forms 添加引用。
	System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
#endif

	// TODO: 将以下应用程序 ID 字符串替换为唯一的 ID 字符串；建议的字符串格式
	//为 CompanyName.ProductName.SubProduct.VersionInformation
	SetAppID(_T("DBBrowser.AppID.NoVersion"));

	// TODO: 在此处添加构造代码，
	// 将所有重要的初始化放置在 InitInstance 中
}

// 唯一的 CDBBrowserApp 对象

CDBBrowserApp theApp;


// CDBBrowserApp 初始化

BOOL CDBBrowserApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式，
	//则需要 InitCommonControlsEx()。  否则，将无法创建窗口。
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinAppEx::InitInstance();


	// 初始化 OLE 库
	if (!AfxOleInit())
	{
		AfxMessageBox(IDP_OLE_INIT_FAILED);
		return FALSE;
	}

	AfxEnableControlContainer();

	EnableTaskbarInteraction(FALSE);

	// 使用 RichEdit 控件需要 AfxInitRichEdit2()
	AfxInitRichEdit5();

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小，则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串，
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
	LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)


	InitContextMenuManager();

	InitKeyboardManager();

	InitTooltipManager();
	CMFCToolTipInfo ttParams;
	ttParams.m_bVislManagerTheme = TRUE;
	theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
		RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
	// 注册应用程序的文档模板。  文档模板
	// 将用作文档、框架窗口和视图之间的连接
	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CDBBrowserDoc),
		RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
		RUNTIME_CLASS(CDBBrowserView));
	if (!pDocTemplate)
		return FALSE;
	AddDocTemplate(pDocTemplate);


	// 分析标准 shell 命令、DDE、打开文件操作的命令行
	CCommandLineInfo cmdInfo;
	//ParseCommandLine(cmdInfo);

	// 调度在命令行中指定的命令。  如果
	// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序，则返回 FALSE。
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;
	// 唯一的一个窗口已初始化，因此显示它并对其进行更新
	m_pMainWnd->CenterWindow();
	m_pMainWnd->UpdateWindow();

	TCHAR szFilePath[MAX_PATH + 1] = { 0 };
	GetModuleFileName(NULL, szFilePath, MAX_PATH);
	m_exepath = szFilePath;
	m_exepath.erase(m_exepath.find_last_of('\\') + 1);
	bool update = false;
	if (__argc > 1) {
		std::wstring sel;
		for (int i = 1; i < __argc; i++) {
			std::wstring op = __targv[i];
			std::wstring h = op.substr(0, 2);
			op = op.erase(0, 2);
			if (h == L"-o") {
				size_t pos = op.find(L';');
				if (pos != std::wstring::npos) {
					std::wstring pa = op.substr(0, pos);
					std::wstring pa2 = op.substr(pos + 1);
					if (PathFileExists(pa.data())) {
						OpenDB(pa.data(), _T("main"));
						if (PathFileExists(pa2.data())) { OpenDB(pa2.data(), _T("extend")); }
					}
				}
				else if (PathFileExists(op.data())) {
					OpenDB(op.data(), _T("main"));
				}
				else if (op == L":memory:")
					OpenDB(op.data(), _T("main"));
			}
			else if (h == L"-s")
				sel = op;
			else if (h == L"-h" || h == L"-hide") {
				m_pMainWnd->ShowWindow(SW_HIDE);
			}
			else if (h == L"-update")
				update = true;
		}
		if (!sel.empty())
			SelectNode(sel.data());
	}
	else if (PathFileExists(L"Data\\ciku.db")) {
		OpenDB(CString("Data\\ciku.db"), (CString)"main");
		if (PathFileExists(L"Data\\ciku_extend.db")) {
			OpenDB(CString("Data\\ciku_extend.db"), (CString)"extend");
		}
	}
	else if (PathFileExists(L"ciku.db")) {
		OpenDB(CString(L"ciku.db"), (CString)"main");
		if (PathFileExists(L"ciku_extend.db")) {
			OpenDB(CString(L"ciku_extend.db"), (CString)"extend");
		}
	}
	(CRichEditCtrl*)(((CFrameWndEx*)AfxGetMainWnd())->GetPane(ID_RICH_PANE)->GetDlgItem(ID_EDIT_CELL))->SendMessage(EM_LIMITTEXT, 0x7FFFFFFE, 0);
	if (update)
		CheckUpdate();
	((CMainFrame*)AfxGetMainWnd())->init = true;
	return TRUE;
}

int CDBBrowserApp::ExitInstance()
{
	//TODO: 处理可能已添加的附加资源
	AfxOleTerm(FALSE);
	m_pRecentFileList->Remove(0);
	//CleanState();
	return CWinAppEx::ExitInstance();
}

// CDBBrowserApp 消息处理程序


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg() noexcept;

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
	virtual BOOL OnInitDialog();
};

CAboutDlg::CAboutDlg() noexcept : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BOOL CAboutDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	CString t;

	GetDlgItemText(IDC_STATIC1, t);
	t += ((CDBBrowserApp*)AfxGetApp())->GetAppVersion().data();
	SetDlgItemText(IDC_STATIC1, t);
	return TRUE;
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()

// 用于运行对话框的应用程序命令
void CDBBrowserApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}

void CDBBrowserApp::OnFileAttach()
{
	CFileDialog dlg(TRUE, _T("*.db"), NULL,
		OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
		_T("SQLite3 Files (*.db)|*.db||"), NULL);
	dlg.m_ofn.lpstrTitle = _T("附加数据库");
	if (dlg.DoModal() == IDOK)
	{
		CString path = dlg.GetPathName(); // 文件路径
		CAttachDlg dlg2;
		dlg2.database = dlg.GetFileTitle();
		if (dlg2.DoModal() == IDOK) {
			OpenDB(path, dlg2.database);
		}
	}
}

void CDBBrowserApp::OnFileOpen()
{
	CFileDialog dlg(TRUE, _T("*.db"), NULL, OFN_HIDEREADONLY,
		_T("SQLite数据库文件 (*.db)|*.db||"), NULL);
	dlg.m_ofn.lpstrTitle = _T("打开数据库");
	if (dlg.DoModal() == IDOK)
	{
		CString path = dlg.GetPathName(); // 文件路径
		OpenDB(path, CString("main"));
	}
}

void CDBBrowserApp::OnFileSaveToTxt()
{
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	if (pDoc->m_table == L"") { return; }
	CFileDialog dlg(FALSE, _T("*.csv;*.txt"), NULL,
		OFN_OVERWRITEPROMPT,
		_T("CSV UTF-8 (逗号分隔)(*.csv,*.txt)|*.csv;*.txt|CSV UTF-16 (制表符分隔)(*.csv,*.txt)|*.csv;*.txt||"), NULL);
	dlg.m_ofn.lpstrTitle = _T("导出当前数据库");
	if (dlg.DoModal() == IDOK)
	{
		CString path = dlg.GetPathName(); // 文件路径
		_EXPORTDB *im = new _EXPORTDB;
		im->path = path;
		im->sql = GenerateSQL(pDoc->m_table) + sqlite::utility::utf8_to_utf16(pDoc->m_sql_where + pDoc->m_sql_order).data();
		im->pDoc = pDoc;
		im->utf16 = dlg.m_ofn.nFilterIndex == 1 ? false : true;
		im->delimiter = dlg.m_ofn.nFilterIndex == 1 ? ',' : '\t';
		if (pDoc->m_task == nullptr) {
			pDoc->m_task = new _TASK;
		}
		im->taskid = pDoc->m_task->tasks;
		pDoc->m_task->tasks++;
		pDoc->m_task->comp.push_back(0);
		pDoc->m_task->total += pDoc->m_rowcount;
		((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->SetTimer(2, 50, 0);
		AfxBeginThread(ExportTableToFileByThread, im);
	}
}

void CDBBrowserApp::OnFileSaveIncToTxt()
{
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	if (pDoc->m_table == L"") { return; }
	CFileDialog dlg1(TRUE, _T("*.db"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
		_T("SQLite数据库文件 (*.db)|*.db||"), NULL);
	dlg1.m_ofn.lpstrTitle = _T("选择对比的数据库");
	if (dlg1.DoModal() == IDOK) {
		CString path = dlg1.GetPathName();
		pDoc->m_db << _T("attach database '") + path + _T("' as '@demo@'");
		std::wstring sql;
		std::wcmatch res;
		std::regex_match(pDoc->m_table.GetString(), res, std::wregex(L"^([^\\.]+\\.)?'?([^\\.]+?)'?$"));
		std::wstring t = res[2];
		
		pDoc->m_db << L"SELECT sql FROM '@demo@'.sqlite_master WHERE type = 'table' AND name = '" + t + L"' limit 1"
			>> [&](std::wstring s) { sql = s; };
		if (sql.empty()) {
			pDoc->m_db << "detach database '@demo@'";
			AfxMessageBox(path + _T("中不存在表：") + t.data(), 48);
			return;
		}
		CFileDialog dlg(FALSE, _T("*.csv;*.txt"), NULL,
			OFN_OVERWRITEPROMPT,
			_T("CSV UTF-8 (逗号分隔)(*.csv,*.txt)|*.csv;*.txt|CSV UTF-16 (制表符分隔)(*.csv,*.txt)|*.csv;*.txt||"), NULL);
		dlg.m_ofn.lpstrTitle = _T("导出增量部分");
		if (dlg.DoModal() == IDOK) {
			CString path = dlg.GetPathName(); // 文件路径
			_EXPORTDB *im = new _EXPORTDB;
			im->path = path;
			im->sql = _T("select * from 'temp'.'@Export@'");
			im->pDoc = pDoc;
			im->utf16 = dlg.m_ofn.nFilterIndex == 1 ? false : true;
			im->delimiter = dlg.m_ofn.nFilterIndex == 1 ? ',' : '\t';
			((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->SetTimer(2, 50, 0);
			if (pDoc->m_task == nullptr) {
				pDoc->m_task = new _TASK;
			}
			im->taskid = pDoc->m_task->tasks;
			pDoc->m_task->tasks++;
			pDoc->m_task->comp.push_back(0);
			if (pDoc->m_transaction)
				pDoc->m_db << "end;";
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
			sql = L"PRAGMA " + std::wstring(res[1].first, res[1].second) + L"table_info('" + t + L"')";
			std::wstring cols;
			pDoc->m_db << sql >> [&](std::wstring cid, std::wstring name) { if (name != L"jp") { cols += L"," + name; } };
			cols.erase(0, 1);
			pDoc->m_db << _T("create temporary table '@Export@' as select ") + cols + _T(" from ") + pDoc->m_table.GetString();
			cols = std::regex_replace(cols, std::wregex(L",(comment|weight)", std::wregex::icase), L"");
			cols = std::regex_replace(cols, std::wregex(L","), L"||'|'||");
			pDoc->m_db << L"delete from 'temp'.'@Export@' where " + cols + L" in (select " + cols + L" from '@demo@'.'" + t + L"')";
			int n;
			pDoc->m_db << "select count(*) from 'temp'.'@Export@'" >> n;
			pDoc->m_task->total += n;
			ExportTableToFileByThread(im);
			pDoc->m_db << "drop table 'temp'.'@Export@'";
			pDoc->m_db << "end;";
			pDoc->m_transaction = false;
			pDoc->m_db << "detach database '@demo@'";;
		}
	}
}

// CDBBrowserApp 自定义加载/保存方法

void CDBBrowserApp::PreLoadState()
{
	BOOL bNameValid;
	CString strName;
	bNameValid = strName.LoadString(IDS_EDIT_MENU);
	ASSERT(bNameValid);
	GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
	bNameValid = strName.LoadString(IDS_EXPLORER);
	ASSERT(bNameValid);
	GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EXPLORER);
	GetContextMenuManager()->AddMenu(L"编辑", IDR_POPUP_RICH);
}

void CDBBrowserApp::LoadCustomState()
{
}

void CDBBrowserApp::SaveCustomState()
{
}

// CDBBrowserApp 消息处理程序

void CDBBrowserApp::CloseDB()
{
	// TODO: 在此处添加实现代码.
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	pDoc->m_db.close();
	pDoc->lastsql = "";
	pDoc->m_sql = "";
	pDoc->m_sql_order = "";
	pDoc->m_sql_select = "";
	pDoc->m_sql_where = "";
	std::map<int, std::vector<std::vector<std::wstring>>> empty;
	pDoc->m_data.swap(empty);
	pDoc->m_tree.clear();
	pView->m_List.SetRedraw(FALSE);
	for (int i = 0; i < pDoc->m_columncount; i++) { pView->m_List.DeleteColumn(0); }
	pDoc->m_rowcount = 0;
	pDoc->m_columncount = 0;
	pDoc->m_rowid = -1;
	pDoc->m_table = _T("");
	pDoc->m_root = L"";
	pDoc->m_tbl = L"";
	pDoc->m_transaction = false;
	pDoc->SetTitle(_T(""));
	pView->m_List.SetItemCount(0);
	pView->m_List.SetRedraw(TRUE);
	pView->m_focus.changed = false;
	pView->m_focus.iItem = -1;
	pView->m_focus.iSubItem = 0;
	pView->UpdateRichEdit();
	CViewTree *tree = (CViewTree*)(((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW)->GetDlgItem(ID_VIEW_CLASSVIEW2));
	tree->DeleteAllItems();
}

void CDBBrowserApp::OpenDB(CString path, CString database)
{
	// TODO: 在此处添加实现代码.
	static bool init = false;
	if (!init) {
		bool is64bit = (sizeof(char*) == 8);
		std::wstring subpath = (is64bit ? L"Lib\\Dll_x64\\SQLite3.dll" : L"Lib\\Dll_x86\\SQLite3.dll");
		if (PathFileExistsW((m_exepath + subpath).data())) {
			if (isPE64(m_exepath + subpath) != is64bit) {
				AfxMessageBox((m_exepath + subpath + (is64bit ? L"非64位版本！" : L"非32位版本！")).data(), MB_ICONSTOP);
				return;
			}
			SetDllDirectory((m_exepath + subpath.substr(0, 12)).data());
		}
		else if (PathFileExistsW((m_exepath + L"SQLite3.dll").data())) {
			if (isPE64(m_exepath + L"SQLite3.dll") != is64bit) {
				AfxMessageBox((m_exepath + L"SQLite3.dll" + (is64bit ? L"非64位版本！" : L"非32位版本！")).data(), MB_ICONSTOP);
				return;
			}
			SetDllDirectory(m_exepath.data());
		}
		else {
			AfxMessageBox(L"找不到SQLite3.dll，无法打开数据库。", MB_ICONSTOP);
			return;
		}
		init = true;
	}
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CViewTree *tree = (CViewTree*)(((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW)->GetDlgItem(ID_VIEW_CLASSVIEW2));
	try
	{
		if (database == L"main") {
			CloseDB();
			pDoc->m_db.open((char16_t*)path.GetString());
		}
		else {
			pDoc->m_db << _T("attach '") + path + _T("' as '") + database + _T("'");
		}
		auto p = pDoc->m_db << _T("SELECT type,name FROM '") + database + _T("'.sqlite_master ORDER by tbl_name");
		HTREEITEM hRoot = tree->InsertItem(database, 2, 2);
		std::vector<std::wstring> tbls;
		pDoc->m_tree[database] = tbls;
		HTREEITEM hTable = tree->InsertItem(_T("表"), 0, 0, hRoot);
		HTREEITEM hIndex = tree->InsertItem(_T("索引"), 0, 0, hRoot);
		while (p.step() == SQLITE_ROW) {
			if (std::wstring(p.get_text16(0)) == L"table") {
				const wchar_t *st = p.get_text16(1);
				pDoc->m_tree[database].push_back(st);
				HTREEITEM node = tree->InsertItem(st, 5, 5, hTable);
				pDoc->m_db << L"PRAGMA '" + database + L"'.table_info('" + CString(st) + L"')" >> [&](std::wstring s1, std::wstring s2, std::wstring s3) {
					tree->InsertItem((s2 + L"(" + s3 + L")").data(), 6, 6, node);
				};
			}
			else {
				const wchar_t *st = p.get_text16(1);
				HTREEITEM node = tree->InsertItem(st, 3, 3, hIndex);
				pDoc->m_db << L"PRAGMA '" + database + L"'.index_info('" + CString(st) + L"')" >> [&](std::wstring s1, std::wstring s2, std::wstring s3) {
					tree->InsertItem(s3.data(), 4, 4, node);
				};
			}
		}
		tree->Expand(hRoot, TVE_EXPAND);
		tree->Expand(hTable, TVE_EXPAND);
		//tree->Expand(hIndex, TVE_EXPAND);
		pDoc->m_db.define("REGEXP", [&](std::string regstr, std::string str) {
			return std::regex_search(str, std::regex(regstr));
		});
		pDoc->m_db.define("SZM", [&](std::string str) {
			return dbother::getpyszm(str);
		});
		pDoc->m_db.define("T2S", [&](std::string str) {
			return pDoc->trad2simp(str);
		});
		pDoc->m_db.define("IsGB2312", [&](std::string str) {
			return pDoc->IsGB2312(str);
		});
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*this->m_pMainWnd, e.get_msg(), 0, 0);
		if (database == L"main") { CloseDB(); }
		return;
	}
}

void CDBBrowserApp::SelectNode(CString Node, CString Root)
{
	// TODO: 在此处添加实现代码.
	CViewTree *tree = (CViewTree*)(((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW)->GetDlgItem(ID_VIEW_CLASSVIEW2));
	HTREEITEM hroot = tree->GetRootItem();
	if (Root != _T("")) {
		while (hroot && tree->GetItemText(hroot).CompareNoCase(Root)) {
			hroot = tree->GetNextItem(hroot, TVGN_NEXT);
		}
	}
	HTREEITEM hchild = tree->GetNextItem(hroot, TVGN_CHILD);
	while (hchild && tree->GetItemText(hchild) != _T("表")) {
		hchild = tree->GetNextItem(hchild, TVGN_NEXT);
	}
	if (hchild && tree->GetItemText(hchild) == _T("表")) {
		HTREEITEM hnode = tree->GetNextItem(hchild, TVGN_CHILD);
		while (hnode && tree->GetItemText(hnode).CompareNoCase(Node)) {
			hnode = tree->GetNextItem(hnode, TVGN_NEXT);
		}
		if (hnode && !tree->GetItemText(hnode).CompareNoCase(Node)) {
			tree->SelectItem(hnode);
			return;
		}
	}
	if (Root == _T("")) {
		while ((hroot = tree->GetNextItem(hroot, TVGN_NEXT)) != NULL) {
			hchild = tree->GetNextItem(hroot, TVGN_CHILD);
			while (hchild && tree->GetItemText(hchild) != _T("表")) {
				hchild = tree->GetNextItem(hroot, TVGN_NEXT);
			}
			if (hchild && tree->GetItemText(hchild) == _T("表")) {
				HTREEITEM hnode = tree->GetNextItem(hchild, TVGN_CHILD);
				while (hnode && tree->GetItemText(hnode).CompareNoCase(Node)) {
					hnode = tree->GetNextItem(hnode, TVGN_NEXT);
				}
				if (hnode && !tree->GetItemText(hnode).CompareNoCase(Node)) {
					tree->SelectItem(hnode);
					return;
				}
			}
		}
	}
}


void CDBBrowserApp::OnUpdateStatic1(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	switch (pCmdUI->m_nID)
	{
	case ID_BEGIN:
		pCmdUI->Enable(pDoc->m_db.connection() && pDoc->m_transaction != true);
		break;
	case ID_FILE_SAVE_TO:
	case ID_FILE_SAVE_INC:
		pCmdUI->Enable(pDoc->m_table != "");
		break;
	case ID_EDIT_INSERT:
		pCmdUI->Enable(pDoc->m_table != "" && !((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.m_Edit.IsWindowVisible());
		break;
	case ID_EDIT_INSCLIP:
		pCmdUI->Enable(pDoc->m_table != ""
			&& !((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.m_Edit.IsWindowVisible()
			&& ::IsClipboardFormatAvailable(CF_UNICODETEXT));
		break;
	default:
		pCmdUI->Enable(pDoc->m_db.connection() ? TRUE : FALSE);
		break;
	}
}


void CDBBrowserApp::OnUpdateAutoTrans(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	pCmdUI->SetCheck(pDoc->m_autotrans);
}


void CDBBrowserApp::OnAutoTrans()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	pDoc->m_autotrans = !pDoc->m_autotrans;
}


void CDBBrowserApp::OnBegin()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	try {
		pDoc->m_db << "begin;";
		pDoc->m_transaction = true;
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*this->m_pMainWnd, e.get_msg(), 0, 0);
	}
}


void CDBBrowserApp::OnEndedit()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.SetFocus();
	CMFCRibbonEdit *edit = DYNAMIC_DOWNCAST(CMFCRibbonEdit, ((CMainFrame*)AfxGetMainWnd())->GetRibbonBar()->FindByID(ID_EDIT_SQLRUN));
	edit->SetEditText(L"");
	try {
		pDoc->m_db << "commit;";
		pDoc->m_transaction = false;
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*this->m_pMainWnd, e.get_msg(), 0, 0);
	}
}


void CDBBrowserApp::OnRollback()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.SetFocus();
	CMFCRibbonEdit *edit = DYNAMIC_DOWNCAST(CMFCRibbonEdit, ((CMainFrame*)AfxGetMainWnd())->GetRibbonBar()->FindByID(ID_EDIT_SQLRUN));
	edit->SetEditText(L"");
	try {
		pDoc->m_db << "rollback;";
		pDoc->m_transaction = false;
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*this->m_pMainWnd, e.get_msg(), 0, 0);
		return;
	}
	auto pcv = (CClassView*)((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW);
	pcv->ReBuildTree();
	if (pDoc->m_sql != "") {
		CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
		try {
			auto t = pDoc->m_db << pDoc->m_sql;
			t.used(true);
			pDoc->databaseadapter(pDoc->m_sql, false);
		}
		catch (sqlite::sqlite_exception) {
			pView->m_List.SetItemCount(0);
			for (int i = 0; i < pDoc->m_columncount; i++) { pView->m_List.DeleteColumn(0); }
			pDoc->Cleartblinfo();
			pView->m_focus.iItem = -1;
			pView->m_focus.iSubItem = 0;
			pDoc->SetTitle(L"");
		}
		pView->ReFresh();
		pView->UpdateRichEdit();
	}
}


void CDBBrowserApp::OnUpdateTrans(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	pCmdUI->Enable(pDoc->m_transaction);
}


void CDBBrowserApp::OnSearchedit()
{
	// TODO: 在此添加命令处理程序代码
	CMFCRibbonBar *pRibbon = ((CMainFrame*)AfxGetMainWnd())->GetRibbonBar();
	CMFCRibbonEdit *edit = DYNAMIC_DOWNCAST(CMFCRibbonEdit, pRibbon->FindByID(ID_SEARCHEDIT));
	CMFCRibbonComboBox *mode = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_SEARCHCOMBO));
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	ASSERT_VALID(edit);
	if (pDoc->m_db.connection() == nullptr || pDoc->m_sql_select == "") { return; }
	CString str = edit->GetEditText();
	if (str == L"") {
		pDoc->m_sql_where = "";
	}
	else {
		int cursel = mode->GetCurSel();
		if (cursel == 4) {
			std::string search = sqlite::utility::utf16_to_utf8(str.GetString());
			pDoc->m_sql_where = " where " + search;
		}
		else {
			CMFCRibbonComboBox *pColcombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_COLCOMBO));
			CString colname = pColcombo->GetEditText();
			if (colname == L"") { return; }
			std::string ucol = sqlite::utility::utf16_to_utf8(colname.GetString());
			std::string search = sqlite::utility::utf16_to_utf8(str.GetString());
			search = pystring::replace(search, "'", "''");
			if (cursel == 1) {
				pDoc->m_sql_where = " where " + ucol + " like '%" + search + "%'";
			}
			else {
				pDoc->m_sql_where = " where " + ucol
					+ (cursel == 0 ? " = '" : cursel == 2 ? " like '" : " regexp '") + search + "'";
			}
		}
	}
	pDoc->databaseadapter(pDoc->m_sql_select + pDoc->m_sql_where + pDoc->m_sql_order, false);
}


void CDBBrowserApp::OnUpadteSearch(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	if (pDoc->m_db.connection() == nullptr) {
		pCmdUI->Enable(FALSE);
	}
	else {
		if (pCmdUI->m_nID == ID_COLCOMBO) {
			CMFCRibbonBar *pRibbon = ((CMainFrame*)AfxGetMainWnd())->GetRibbonBar();
			CMFCRibbonComboBox *combo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_SEARCHCOMBO));
			pCmdUI->Enable(combo->GetCurSel() != 4);
		}
		else { pCmdUI->Enable(TRUE); }
	}
}


void CDBBrowserApp::OnUpdateEditDel(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	POSITION pos = pView->m_List.GetFirstSelectedItemPosition();
	pCmdUI->Enable(pos && pDoc->m_rowid > -1 && !pView->m_List.m_Edit.IsWindowVisible() ? TRUE : FALSE);
}


void CDBBrowserApp::OnUpdateEditCell(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	//POSITION pos = pView->m_List.GetFirstSelectedItemPosition();
	pCmdUI->Enable(pView->m_focus.changed ? TRUE : FALSE);
}


void CDBBrowserApp::ExportAllTableToFile()
{
	// TODO: 在此处添加实现代码.
	CFolderPickerDialog dlg(NULL, 0, m_pMainWnd, 0, 0);
	if (dlg.DoModal() != IDOK) { return; }
	CString Rpath = dlg.GetPathName() + L"\\";

	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();

	for (auto it = pDoc->m_tree.begin(); it != pDoc->m_tree.end(); it++) {
		for (size_t i = 0; i < it->second.size(); i++) {
			_EXPORTDB *im = new _EXPORTDB;
			//im->path = path;
			time_t rawtime;
			wchar_t buffer[80];
			time(&rawtime);
			struct tm t;
			localtime_s(&t, &rawtime);
			wcsftime(buffer, 80, L"%Y-%m-%d_%H%M%S", &t);
			CString path;
			{
				path = Rpath + (it->second[i] + L"_" + buffer).data();
			}
			im->path = path + L".csv";
			int id = 0;
			while (PathFileExists(path + L".csv")) {
				id++;
				im->path = path + L"_" + std::to_wstring(id).data() + L".csv";
			}
			im->sql = GenerateSQL(_T("'") + it->first + _T("'.'") + it->second[i].data() + _T("'"));
			im->pDoc = pDoc;
			im->utf16 = false;
			im->delimiter = ',';
			int rowc = 0;
			pDoc->m_db << (_T("select count(*) from '") + it->first + _T("'.'") + it->second[i].data() + _T("'")).GetString() >> rowc;
			if (pDoc->m_task == nullptr) {
				pDoc->m_task = new _TASK;
			}
			im->taskid = pDoc->m_task->tasks;
			pDoc->m_task->tasks++;
			pDoc->m_task->comp.push_back(0);
			pDoc->m_task->total += rowc;
			((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->SetTimer(2, 50, 0);
			AfxBeginThread(ExportTableToFileByThread, im);
		}
	}
}


CString CDBBrowserApp::GenerateSQL(CString tbl)
{
	// TODO: 在此处添加实现代码.
	if (std::regex_search(tbl.GetString(), std::wregex(L"pinyin", std::wregex::icase))) {
		return _T("select key,value,weight from ") + tbl;
	}
	else { return _T("select * from ") + tbl; }
}


void CDBBrowserApp::ImportCSVToDB()
{
	// TODO: 在此处添加实现代码.
	CFileDialog dlg(TRUE, _T("*.txt|*.csv"), NULL,
		OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
		_T("文本文件 (*.txt;*.csv)|*.txt;*.csv||"), NULL);
	dlg.m_ofn.lpstrTitle = _T("导入词库");
	if (dlg.DoModal() == IDOK)
	{
		CString path = dlg.GetPathName(); // 文件路径
		std::wstring name = std::regex_replace(dlg.GetFileTitle().GetString(), std::wregex(L"_.*$"), L"");
		ImportCSVToDB(path, name);
	}
}


void CDBBrowserApp::ImportCSVToDB(CString path, std::wstring name)
{
	CPreImportDlg dlg2;
	dlg2.m_tbl.push_back((L"'" + name + L"'").data());
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	auto tree = &pDoc->m_tree;
	for (auto b = tree->begin(); b != tree->end(); b++) {
		for (size_t i = 0; i < b->second.size(); i++) {
			if (name == b->second[i] && dlg2.m_tbl[0].Find((L"'.'" + name).data()) == -1) {
				dlg2.m_tbl[0] = L"'" + b->first + L"'.'" + b->second[i].data() + L"'";
			}
			else {
				dlg2.m_tbl.push_back(L"'" + b->first + L"'.'" + b->second[i].data() + L"'");
			}
		}
	}
	auto mmap = mio::mmap_source(path.GetString());
	dlg2.buffer = mmap.data(), dlg2.dwsize = mmap.size();
	if (dlg2.DoModal() == IDOK) {
		_IMPORTDB *im = new _IMPORTDB;
		CString sql = _T("insert into ") + dlg2.selck + _T(" values(");
		if (dlg2.selck.Find(_T("pinyin")) != -1) {
			sql += _T("?4,"); im->pinyin = true;
		}
		for (size_t i = 0; i < dlg2.m_viewdata.size(); i++) {
			if (i > 0) { sql += _T(","); }
			sql += _T("?") + dlg2.m_viewdata[i][0];
		}
		sql += _T(")");
		im->CRLF = dlg2.CRLF;
		im->pGen = dlg2.pGen;
		im->default = sqlite::utility::utf16_to_utf8(dlg2.def.GetString());
		if (dlg2.m_viewdata.size() > 1) {
			im->keyindex = dlg2.m_viewdata[0][0][0] - '1';
			im->valueindex = dlg2.m_viewdata[1][0][0] - '1';
		}
		im->duoyi = dlg2.isduoyi;
		im->delimiter = dlg2.delimiter;
		im->path = path;
		im->first_row_is_header = dlg2.firstishead;
		if (im->pinyin && im->pGen)
			im->pGen->JiebaInit(((CDBBrowserDoc*)((CFrameWndEx*)AfxGetMainWnd())->GetActiveDocument())->GetJieba());
		im->sql = sql;
		im->pDoc = pDoc;
		if (pDoc->m_task == nullptr) {
			pDoc->m_task = new _TASK;
		}
		im->taskid = pDoc->m_task->tasks;
		pDoc->m_task->tasks++;
		pDoc->m_task->comp.push_back(0);
		((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->SetTimer(2, 50, 0);
		AfxBeginThread(ImportTableByThread, im);
	}
	else if (dlg2.pGen) { delete dlg2.pGen; }
}


void CDBBrowserApp::ReFresh()
{
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	if (GetFocus() == pView->m_List.m_hWnd) {
		if (pView->m_List.m_Edit.IsWindowVisible() || pDoc->m_sql == "") { return; }
		pDoc->databaseadapter(pDoc->m_sql, false);
	}
	else {
		auto pcv = (CClassView*)((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW);
		if (GetFocus() == pcv->GetDlgItem(ID_VIEW_CLASSVIEW2)->m_hWnd && pDoc->m_db.connection()) {
			pcv->ReBuildTree();
		}
	}
}


void CDBBrowserApp::OnEditDel()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	POSITION pos = pView->m_List.GetFirstSelectedItemPosition();
	if (!pos) { return; }
	int index = pView->m_List.GetNextSelectedItem(pos);
	int first = index;
	int page = index / pDoc->m_pagesize;
	int iItem = index % pDoc->m_pagesize;
	int begin = page, delrows = 0;
	try {
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		CString sql = _T("delete from ") + pDoc->m_table + _T(" where rowid = ");
		if (pDoc->m_data[page][iItem][pDoc->m_rowid] != L"") {
			pDoc->m_db << (sql + pDoc->m_data[page][iItem][pDoc->m_rowid].data()).GetString();
			delrows++;
		}
		pView->m_List.SetItemState(index, 0, LVIS_SELECTED | LVIS_FOCUSED);
		while (pos) {
			index = pView->m_List.GetNextSelectedItem(pos);
			page = index / pDoc->m_pagesize;
			iItem = index % pDoc->m_pagesize;
			if (pDoc->m_data[page][iItem][pDoc->m_rowid] != L"") {
				pDoc->m_db << (sql + pDoc->m_data[page][iItem][pDoc->m_rowid].data()).GetString();
				delrows++;
			}
			pView->m_List.SetItemState(index, 0, LVIS_SELECTED | LVIS_FOCUSED);
		}
		pDoc->m_data.erase(pDoc->m_data.find(begin), pDoc->m_data.end());
		pView->m_List.SetSelectionMark(-1);
		pDoc->m_rowcount -= delrows;
		if (pDoc->m_slowmode) {
			pDoc->m_itemcount = pDoc->m_rowcount;
		}
		else {
			pDoc->m_db << "select max(_rowid_) from (" + pDoc->m_sql_select + pDoc->m_sql_where + ");" >> pDoc->m_itemcount;
		}
		pView->m_List.SetItemCount(pDoc->m_itemcount);
		pView->m_List.EnsureVisible(first, TRUE);
		pView->ReFresh();
		auto pStatusBar = (CMFCRibbonStatusBar*)((CFrameWndEx*)AfxGetMainWnd())->GetPane(AFX_IDW_STATUS_BAR);
		auto pStatusBarPane = (CMFCRibbonStatusBarPane*)(pStatusBar->FindElement(ID_STATUSBAR_PANE2));
		CString jls;
		jls.Format(_T("共%d条"), pDoc->m_rowcount);
		pStatusBarPane->SetText(jls);
		pStatusBarPane->Redraw();
		pView->m_List.SetItemState(first, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
		pView->UpdateRichEdit();
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*m_pMainWnd, e.get_msg(), 0, 0);
	}
}


void CDBBrowserApp::OnEditSqlrun()
{
	// TODO: 在此添加命令处理程序代码
	CMFCRibbonBar *pRibbon = ((CMainFrame*)AfxGetMainWnd())->GetRibbonBar();
	CMFCRibbonEdit *edit = DYNAMIC_DOWNCAST(CMFCRibbonEdit, pRibbon->FindByID(ID_EDIT_SQLRUN));
	CString sql = edit->GetEditText();
	if (sql == _T("")) { return; }
	if (std::regex_search(sql.GetString(), std::wregex(L"^\\s*(select|pragma|begin|commit|rollback)", std::wregex::icase))) { edit->SetEditText(L""); return; }
	auto pinfo = new _THREADPTR;
	pinfo->data = (LPVOID)sql.GetString();
	AfxBeginThread(SqlRunByThread, pinfo);
}


void CDBBrowserApp::OnEditInsert()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	try {
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		CString sql;
		sql.Format(_T("insert into %s default values;"), pDoc->m_table);
		pDoc->m_db << sql.GetString();
		pView->m_List.EnsureVisible(pDoc->m_itemcount - 1, FALSE);
		pDoc->m_itemcount += 1;
		pDoc->m_rowcount += 1;
		pView->m_List.SetItemCount(pDoc->m_itemcount);
		int page = pDoc->m_itemcount / pDoc->m_pagesize;
		auto it = pDoc->m_data.find(page);
		if (it != pDoc->m_data.end()) {
			auto last_ = pDoc->m_db.last_insert_rowid();
			if (pDoc->m_data[page].size() >= pDoc->m_pagesize) {
				std::vector<std::vector<std::wstring>> pagedata;
				page++; pDoc->m_data[page] = pagedata;
			}
			CString sql;
			sql.Format(_T("select * from %s where rowid=%d;"), pDoc->m_table, last_);
			auto ps = pDoc->m_db << sql.GetString();
			int cols = ps.get_column_count();
			std::vector<std::wstring> line;
			line.push_back(std::to_wstring(last_));
			ps.step();
			for (int i = 0; i < cols; i++) {
				auto ch = ps.get_text16(i);
				line.push_back(ch ? ch : L"");
			}
			pDoc->m_data[page].push_back(line);
		}
		POSITION pos = pView->m_List.GetFirstSelectedItemPosition();
		while (pos) { pView->m_List.SetItemState(pView->m_List.GetNextSelectedItem(pos), 0, LVIS_SELECTED | LVIS_FOCUSED); }
		pView->m_List.SetFocus();
		pView->m_List.EnsureVisible(pDoc->m_itemcount - 1, FALSE);
		pView->m_List.SetItemState(pDoc->m_itemcount - 1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
		auto pStatusBar = (CMFCRibbonStatusBar*)((CFrameWndEx*)AfxGetMainWnd())->GetPane(AFX_IDW_STATUS_BAR);
		auto pStatusBarPane = (CMFCRibbonStatusBarPane*)(pStatusBar->FindElement(ID_STATUSBAR_PANE2));
		CString jls;
		jls.Format(_T("共%d条"), pDoc->m_rowcount);
		pStatusBarPane->SetText(jls); pDoc->m_newrow = 1;
		pStatusBarPane->Redraw();
		if (m_dicttbl != pDoc->m_table) {
			COPYDATASTRUCT data;
			data.dwData = 3;
			data.cbData = (pDoc->m_tbl.size() + 1) * sizeof(pDoc->m_tbl[0]);
			data.lpData = (PVOID)pDoc->m_tbl.data();
			m_pMainWnd->SendMessage(WM_COPYDATA, 0, (LPARAM)&data);
			m_dicttbl = pDoc->m_table;
		}
		if (pDoc->m_codegen) {
			if (std::regex_search(pDoc->m_tbl, std::wregex(L"pinyin", std::wregex::icase)))
				pView->EditCell(pDoc->m_itemcount - 1, 3);
			else
				pView->EditCell(pDoc->m_itemcount - 1, 2);
		}
		else
			pDoc->m_newrow = 2, pView->EditCell(pDoc->m_itemcount - 1, 1);
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*m_pMainWnd, e.get_msg(), 0, 0);
	}
}


void CDBBrowserApp::OnEditInsClip()
{
	if (::OpenClipboard(m_pMainWnd->m_hWnd)) {
		HGLOBAL hMem = ::GetClipboardData(CF_UNICODETEXT);
		if (hMem != NULL) {
			const char *buffer = (const char*)::GlobalLock(hMem);
			SIZE_T dwsize = ::GlobalSize(hMem);
			ImportCSVToDBFromMem(buffer, dwsize - 2);
			::GlobalUnlock(hMem);
		}
		::CloseClipboard();
	}
	else
		return;
}


void CDBBrowserApp::OnRichEditOK()
{
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	CRichEditCtrl *edit = (CRichEditCtrl*)(((CFrameWndEx*)m_pMainWnd)->GetPane(ID_RICH_PANE)->GetDlgItem(ID_EDIT_CELL));
	LV_COLUMN lvc;
	TCHAR szText[16];
	lvc.mask = LVCF_TEXT;
	lvc.pszText = szText;
	lvc.cchTextMax = 16;
	int iSubItem = pView->m_focus.iSubItem;
	int iItem = pView->m_focus.iItem;
	int pageIndex = iItem / pDoc->m_pagesize;
	int iItemIndex = iItem % pDoc->m_pagesize;
	pView->m_List.GetColumn(iSubItem, &lvc);
	CString newtext;
	edit->GetWindowTextW(newtext);
	try {
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		CString sql;
		if (pDoc->m_table.Find(_T("'pinyin'")) != -1 && std::wstring(lvc.pszText) == L"key") {
			sql.Format(_T("update %s set jp = ? , key = ? where _rowid_ = %s;"), pDoc->m_table, pDoc->m_data[pageIndex][iItemIndex][pDoc->m_rowid].data());
			std::wstring wstr = newtext.GetString();
			std::wstring szmstr = dbother::getpyszm(wstr);
			pDoc->m_db << sql
				<< szmstr
				<< wstr;
			pDoc->m_data[pageIndex][iItemIndex][iSubItem] = newtext;
			if (pDoc->m_pyjp > -1) {
				pDoc->m_data[pageIndex][iItemIndex][pDoc->m_pyjp] = szmstr;
			}
		}
		else {
			sql.Format(_T("update %s set %s = ? where _rowid_ = %s;"), pDoc->m_table, lvc.pszText, pDoc->m_data[pageIndex][iItemIndex][pDoc->m_rowid].data());
			pDoc->m_db << sql
				<< newtext.GetString();
			pDoc->m_data[pageIndex][iItemIndex][iSubItem] = newtext;
		}
		pView->ReFresh();
		((CellRichEdit*)((CFrameWndEx*)m_pMainWnd)->GetPane(ID_RICH_PANE))->m_changed = false;
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*m_pMainWnd, e.get_msg(), 0, 0);
	}
}

BOOL CDBBrowserApp::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->wParam == VK_DELETE) {
		if (GetFocus() != ((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.m_hWnd) {
			return FALSE;
		}
	}
	else if (::GetKeyState(VK_CONTROL) < 0){
		if (pMsg->wParam == 'N') {
			if (GetFocus() != ((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.m_hWnd)
				return TRUE;
		}
		else if (pMsg->wParam == 'C' || pMsg->wParam == 'V') {
			if (GetFocus() != ((CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView())->m_List.m_hWnd)
				return FALSE;
		}
	}
	return CWinAppEx::PreTranslateMessage(pMsg);
}


void CDBBrowserApp::OnTbRename()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CAttachDlg dlg;
	std::wcmatch res;
	std::regex_match(pDoc->m_table.GetString(), res, std::wregex(L"^([^\\.]+\\.)?'?([^\\.]+?)'?$"));
	CString root = std::wstring(res[1].first + 1, res[1].second - 1).data();
	dlg.database = std::wstring(res[2].first, res[2].second).data();
	dlg.showtip = L"修改词库名";
	if (dlg.DoModal() == IDOK) {
		if (dlg.database.GetLength() == 0) { return; }
		try {
			if (pDoc->m_autotrans && !pDoc->m_transaction) {
				pDoc->m_db << "begin;";
				pDoc->m_transaction = true;
			}
			CString sql;
			sql.Format(_T("ALTER TABLE %s RENAME TO '%s'"), pDoc->m_table, dlg.database);
			pDoc->m_db << sql;
			auto pcv = (CClassView*)((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW);
			pcv->ReBuildTree();
			SelectNode(dlg.database, root);
		}
		catch (sqlite::sqlite_exception& e) {
			MessageBoxA(*m_pMainWnd, e.get_msg(), 0, 0);
		}
	}
}


void CDBBrowserApp::OnUpdateTbClear(CCmdUI *pCmdUI)
{
	if (!m_pMainWnd) { return; }
	CViewTree *tree = (CViewTree*)(((CFrameWndEx*)m_pMainWnd)->GetPane(ID_VIEW_CLASSVIEW)->GetDlgItem(ID_VIEW_CLASSVIEW2));
	pCmdUI->Enable(!(tree->GetItemText(tree->GetParentItem(tree->GetSelectedItem())) == L"索引"));
}


UINT SqlRunByThread(LPVOID lp)
{
	auto pFra = ((_THREADPTR*)lp)->pFra;
	auto pApp = ((_THREADPTR*)lp)->pApp;
	auto pDoc = ((_THREADPTR*)lp)->pDoc;
	auto pView = ((_THREADPTR*)lp)->pView;
	std::wstring sql = (wchar_t*)((_THREADPTR*)lp)->data;
	
	try {
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		pDoc->m_db << sql;
		if (std::regex_search(sql, std::wregex(L"^\\s*drop\\s+table\\s+", std::wregex::icase))) {
			if (pDoc->m_table != _T("")) {
				try {
					auto t = pDoc->m_db << pDoc->m_sql;
					t.used(true);
					pDoc->databaseadapter(pDoc->m_sql, false);
				}
				catch (sqlite::sqlite_exception) {
					pView->m_List.SetItemCount(0);
					for (int i = 0; i < pDoc->m_columncount; i++) { pView->m_List.DeleteColumn(0); }
					pDoc->Cleartblinfo();
					pView->m_focus.iItem = -1;
					pView->m_focus.iSubItem = 0;
					pDoc->SetTitle(L"");
				}
			}
		}
		else if (pDoc->m_table != _T("")) {
			pView->SetTimer(4, 10, 0);
			//pDoc->databaseadapter(pDoc->m_sql, false);
			//pView->ReFresh();
		}
		if (std::regex_search(sql, std::wregex(L"^\\s*(drop|create)", std::wregex::icase))) {
			((_THREADPTR*)lp)->pCV->ReBuildTree();
		}
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*pFra, e.get_msg(), 0, 0);
	}
	delete (_THREADPTR*)lp;
	return 0;
}

std::wstring CDBBrowserApp::GetAppVersion()
{
	/* 获得程序路径 */
	TCHAR cPath[MAX_PATH];
	::GetModuleFileName(NULL, cPath, MAX_PATH); //获取应用程序路径

	/* 获得版本信息大小 */
	DWORD dwHandle, InfoSize;
	InfoSize = GetFileVersionInfoSize(cPath, &dwHandle); //获取版本信息总体的大小

	if (InfoSize == 0)
		return L"";

	BYTE *InfoBuf = new BYTE[InfoSize];
	UINT uSize = 0;
	VS_FIXEDFILEINFO *pFFI;
	if (!GetFileVersionInfo(cPath, 0, InfoSize, InfoBuf)
		|| !VerQueryValue(InfoBuf, _T("\\"), (LPVOID *)&pFFI, &uSize)) {
		delete[] InfoBuf;
		return L"";
	}
	UINT iFileMS = (UINT)pFFI->dwFileVersionMS;
	UINT iFileLS = (UINT)pFFI->dwFileVersionLS;
	TCHAR version_string[128];  // AutoIt3: 43+1 is the maximum size, but leave a little room to increase confidence.
	wsprintf(version_string, L"%u.%u.%u.%u", (iFileMS >> 16), (iFileMS & 0xFFFF), (iFileLS >> 16), (iFileLS & 0xFFFF));
	delete[] InfoBuf;

	return version_string;
}

void CDBBrowserApp::CheckUpdate()
{
	// TODO: 在此处添加实现代码.
	auto r = Request(L"https://gitee.com/orz707/Yzime/raw/zip/Yzime.ini").get();
	if (r.status == 200) {
		std::wstring version = r.to_wstring();
		std::wsmatch res;
		if (std::regex_search(version, res, std::wregex(L"cikumanager=([\\d\\.]+)$", std::wregex::icase))) {
			version = res[1];
			if (version > GetAppVersion()) {
				if (AfxMessageBox(L"词库管理已更新，是否请前往下载？", 68) == IDYES)
					ShellExecute(NULL, L"open", L"https://wws.lanzous.com/b01bga84b", NULL, NULL, SW_SHOWNORMAL);
			}
			else
				AfxMessageBox(L"已经是最新版本！", 64);
		}
		else
			AfxMessageBox(L"检测更新失败！");
	}
	else
		AfxMessageBox(L"检测更新失败！");
}


bool CDBBrowserApp::isPE64(std::wstring filename)
{
	// TODO: 在此处添加实现代码.
	std::ifstream file(filename, std::ios::binary | std::ios::beg);
	IMAGE_DOS_HEADER Dos;
	file.read((char*)&Dos, sizeof(Dos));
	file.seekg(Dos.e_lfanew);
	IMAGE_NT_HEADERS Nt;
	file.read((char*)&Nt, sizeof(Nt));
	file.close();
	switch (Nt.FileHeader.Machine)
	{
	case IMAGE_FILE_MACHINE_IA64:
	case IMAGE_FILE_MACHINE_AMD64:
		return true;
	default:
		break;
	}
	return false;
}


void CDBBrowserApp::SegTest()
{
	// TODO: 在此处添加实现代码.
	CSegDlg dlg;
	dlg.seg = ((CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument())->GetJieba();
	dlg.DoModal();
}


void CDBBrowserApp::OnEditCopy()
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	POSITION pos = pView->m_List.GetFirstSelectedItemPosition();
	if (!pos) { return; }
	int index = pView->m_List.GetNextSelectedItem(pos);
	int first = index;
	int page = index / pDoc->m_pagesize;
	int iItem = index % pDoc->m_pagesize;
	int begin = page, delrows = 0;
	try {
		std::wstring cols;
		pDoc->m_db << L"PRAGMA '" + pDoc->m_root + L"'.table_info('" + pDoc->m_tbl + L"')"
			>> [&](std::wstring cid, std::wstring name) { if (name != L"jp") { cols += L"," + name; } };
		if (!cols.empty())
			cols.erase(0, 1);
		std::wstring sql = L"select " + cols + L" from " + pDoc->m_table.GetString() + L" where rowid in (";
		cols = L"";
		std::wstring t = pDoc->m_data[page][iItem][pDoc->m_rowid];
		if (t != L"")
			cols += L',', cols += t;
		while (pos) {
			index = pView->m_List.GetNextSelectedItem(pos);
			page = index / pDoc->m_pagesize;
			iItem = index % pDoc->m_pagesize;
			t = pDoc->m_data[page][iItem][pDoc->m_rowid];
			if (t != L"")
				cols += L',', cols += t;
		}
		cols.erase(0, 1);
		if (cols.empty())
			return;
		sql += cols + L')', cols = L"";
		auto p = pDoc->m_db << sql;
		int n = p.get_column_count();
		std::wstring buf = L"", buff = L"", line = L"";
		std::wstring ss = L"\n\r\"\t";
		size_t cur, len;
		while (p.step() == SQLITE_ROW) {
			line.clear();
			for (int i = 0; i < n; i++) {
				auto t = p.get_text16(i);
				line += L'\t';
				if (t) {
					buf = t;
					if (buf.find_first_of(ss) == std::wstring::npos) { line += buf; }
					else {
						cur = buf.find(L"\""), len = buf.size();
						while (cur != std::wstring::npos && cur <= len) {
							buf.replace(cur, 1, L"\"\"");
							cur += 2, len++;
							cur = buf.find(L"\"", cur);
						}
						line += '\"'; line += buf; line += '\"';
					}
				}
			}
			buff += line.data() + 1;
			buff += '\n';
		}
		if (OpenClipboard(m_pMainWnd->m_hWnd))
		{
			HGLOBAL clipbuffer;
			TCHAR *buffer;
			EmptyClipboard();
			clipbuffer = GlobalAlloc(GMEM_MOVEABLE, (buff.size() + 1) * 2);
			buffer = (TCHAR*)GlobalLock(clipbuffer);
			lstrcpy(buffer, buff.data());
			GlobalUnlock(clipbuffer);
			SetClipboardData(CF_UNICODETEXT, clipbuffer);
			CloseClipboard();
		}
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*m_pMainWnd, e.get_msg(), 0, 0);
	}
}


void CDBBrowserApp::ImportCSVToDBFromMem(const char *buffer, SIZE_T dwsize)
{
	// TODO: 在此处添加实现代码.
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)((CFrameWndEx*)m_pMainWnd)->GetActiveDocument();
	CDBBrowserView *pView = (CDBBrowserView*)((CFrameWndEx*)m_pMainWnd)->GetActiveView();
	_IMPORTDB im;
	std::wstring st((wchar_t*)buffer, min(256, dwsize / 2));
	size_t t = st.find_first_of(L"\\r\\n");
	if (t != std::wstring::npos && st[t] == '\\r' && st[t + 1] == '\\n')
		im.CRLF = 2;
	wchar_t *wbuf = (wchar_t*)buffer; bool quo = true;
	for (SIZE_T i = 0; i < dwsize / 2; i++) {
		if (wbuf[i] == '"')
			quo = !quo;
		else if (quo && (wbuf[i] == '\t' || wbuf[i] == ' ' || wbuf[i] == ',' || wbuf[i] == '=')) {
			im.delimiter = wbuf[i];
			break;
		}
	}
	try {
		auto p = pDoc->m_db << L"select * from " + pDoc->m_table;
		int cols = p.get_column_count();
		std::wstring t = p.get_name16(0);
		std::wstring reg(L"^[a-z]+");
		CString sql = _T("insert into ") + pDoc->m_table + _T(" values(");
		if (std::regex_search(pDoc->m_tbl, std::wregex(L"customs|functions|hotstrings|symbol|english|cliphistory", std::wregex::icase))) {
			reg += im.delimiter, reg += L"[^", reg += im.delimiter, reg += L"].*";
			if (std::regex_search(pDoc->m_tbl, std::wregex(L"cliphistory", std::wregex::icase)))
				sql += _T("?"), im.valueindex = 0;
			else if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
				im.keyindex = 0, im.valueindex = 1;
				sql += _T("?");
				for (int i = 1; i < cols; i++)
					sql += _T(",?");
			}
			else {
				reg = L"^.+", reg += im.delimiter, reg += L"[a-z]+(", reg += im.delimiter, reg += L"|\\r|\\n)?";
				if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
					im.keyindex = 1, im.valueindex = 0;
					sql += _T("?2,?1");
					for (int i = 2; i < cols; i++)
						sql += _T(",?"), sql += std::to_wstring(i + 1).data();
				}
				else {
					reg = L"^.+", reg += im.delimiter, reg += L".+?", reg += im.delimiter, reg += L"[a-z]+";
					if (cols == 3 && std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
						im.keyindex = 2, im.valueindex = 0;
						sql += _T("?3,?1,?2");
					}
					else {
						im.keyindex = 0, im.valueindex = 1;
						sql += _T("?");
						for (int i = 1; i < cols; i++)
							sql += _T(",?");
					}
				}
			}
		}
		else {
			if (std::regex_search(pDoc->m_tbl, std::wregex(L"pinyin", std::wregex::icase)) && t == L"jp") {
				sql += _T("?4,"); im.pinyin = true; cols--;
			}
			reg += im.delimiter, reg += L"[^\\x00-\\xff]+(", reg += im.delimiter, reg += L"\\d+)?";
			if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
				im.keyindex = 0;
				im.valueindex = 1;
				sql += _T("?1");
				for (int i = 1; i < cols; i++)
					sql += _T(",?"), sql += std::to_wstring(i + 1).data();
			}
			else {
				reg = L"^[^\\x00-\\xff]+", reg += im.delimiter, reg += L"[a-z]+(", reg += im.delimiter, reg += L"\\d+)?";
				if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
					im.keyindex = 1;
					im.valueindex = 0;
					sql += _T("?2,?1");
					for (int i = 2; i < cols; i++)
						sql += _T(",?"), sql += std::to_wstring(i + 1).data();
				}
				else {
					reg = L"^[^\\x00-\\xff]+", reg += im.delimiter, reg += L"\\d+", reg += im.delimiter, reg += L"[a-z]+";
					if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
						im.valueindex = 0, im.keyindex = 2;
						sql += _T("?3,?1,?2");
						for (int i = 3; i < cols; i++)
							sql += _T(",?"), sql += std::to_wstring(i + 1).data();
					}
					else {
						reg = L"[a-z]+(", reg += im.delimiter, reg += L"[^\\x00-\xff]+){2,}";
						if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
							im.keyindex = 0, im.valueindex = 1, im.duoyi = true;
							sql += _T("?,?,?");
						}
						else {
							reg = L"^[^\\x00-\\xff]+", reg += im.delimiter, reg += L"(\\d+)?([\\r\\n]+)?";
							if (std::regex_search(st, std::wregex(reg, std::wregex::icase))) {
								im.valueindex = 0;
								im.keyindex = cols - 1;
								sql += _T("?3,?1,?2");
								if (m_dicttbl != pDoc->m_table) {
									COPYDATASTRUCT data;
									data.dwData = 3;
									data.cbData = (pDoc->m_tbl.size() + 1) * sizeof(pDoc->m_tbl[0]);
									data.lpData = (PVOID)pDoc->m_tbl.data();
									m_pMainWnd->SendMessage(WM_COPYDATA, 0, (LPARAM)&data);
									m_dicttbl = pDoc->m_table;
								}
								im.pGen = pDoc->m_codegen;
							}
							else {
								auto pStatusBar = (CMFCRibbonStatusBar*)((CFrameWndEx*)AfxGetMainWnd())->GetPane(AFX_IDW_STATUS_BAR);
								auto pProgressBar = (CMFCRibbonProgressBar*)(pStatusBar->FindElement(ID_STATUSBAR_PROGRESS));
								auto pT = pStatusBar->FindElement(ID_STATUSBAR_PANE1);
								pT->SetText(L"数据格式不正确！"), pT->Redraw();
								pProgressBar->SetPos(0);
								pView->SetTimer(3, 10000, 0);
								return;
							}
						}
					}
				}
			}
		}
		sql += _T(")");
		im.default = "";
		if (im.pinyin && im.pGen)
			im.pGen->JiebaInit(pDoc->GetJieba());
		im.sql = sql;
		im.pDoc = pDoc;
		if (pDoc->m_task == nullptr)
			pDoc->m_task = new _TASK;
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		im.taskid = pDoc->m_task->tasks;
		pDoc->m_task->tasks++;
		pDoc->m_task->comp.push_back(0);
		pView->SetTimer(2, 50, 0);
		_import_template<wchar_t, std::wstring>(&im, buffer, dwsize);
		pDoc->m_task->tasks--; pDoc->m_task->fresh = true;
		if (!pDoc->m_task->tasks) { pDoc->m_task->end = clock(); }
		SendMessage(pView->m_List.m_hWnd, WM_KEYDOWN, VK_END, 0);
	}
	catch (sqlite::sqlite_exception& e) {
		pDoc->m_task->tasks--;
		if (!pDoc->m_task->tasks) { pDoc->m_task->end = clock(); }
		pView->KillTimer(2);
		MessageBoxA(*m_pMainWnd, e.get_msg(), 0, 0);
	}
}
